﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Management;
using System.Text;
using System.Collections;
using System.Security.Principal;
using System.Web.Security;

namespace WASM.WebSite.Logic.Logging
{
	public class ExceptionErrorEvent : WebErrorEvent
	{
		private string _message;

		internal ExceptionErrorEvent(Exception exception)
			: base(exception.Message, "CommonErrorLoggingCategory", 505355, exception)
		{
			//piupulate custom output
			StringBuilder info = new StringBuilder();
			info.AppendLine("-------------------------------------");
			Dictionary<string, string> props = CreateMessageProperties();
			foreach (KeyValuePair<string, string> item in props)
			{
				info.AppendLine(String.Format("{0}: {1};", item.Key, item.Value));
			}

			foreach (DictionaryEntry item in exception.Data)
			{
				info.AppendLine(String.Format("{0}: {1};", item.Key, item.Value));
			}

			info.AppendLine("-------------------------------------");

			_message = info.ToString();
		}

		protected virtual Dictionary<string, string> CreateMessageProperties()
		{
			WebProcessInformation processInfo = ProcessInformation;
			WebThreadInformation threadInfo = ThreadInformation;
			HttpContext context = Logger.HttpContext;

			Dictionary<string, string> dic = new Dictionary<string, string>();
			//message header
			dic.Add("DateTime", String.Format("{0}, (UTC) {1}", EventTime, EventTimeUtc));
			dic.Add("Message", Message);
			dic.Add("EventId", EventID.ToString());
			dic.Add("ProcessName", processInfo != null ? processInfo.ProcessName : "<unkown>");
			dic.Add("ProcessAccountName", processInfo != null ? processInfo.AccountName : "<unkown>");
			dic.Add("MachineName", Environment.MachineName);

			//user specific information
			string userInfo = GetUserInfo(context);
			if (!String.IsNullOrEmpty(userInfo))
				dic.Add("User", userInfo);

			//request info
			if (context != null && context.Request != null)
				dic.Add("Requested URL", context.Request.Url.ToString());
			dic.Add("ClientHost", String.Format("Address = {0}", Logger.UserHostAddress ?? "<unknown>"));

			//exception text
			if (ErrorException != null)
			{
				dic.Add("Exception Message", ErrorException.Message);
				dic.Add("Exception Details", ErrorException.ToString());
			}

			//thread information
			if (threadInfo != null)
			{
				StringBuilder threadInfoStr = new StringBuilder();
				threadInfoStr.Append(String.Format("IsImpersonating = {0}", threadInfo.IsImpersonating));
				if (threadInfo.IsImpersonating)
				{
					threadInfoStr.Append(String.Format(" Thread Account Name = {0}", threadInfo.ThreadAccountName));
				}
				dic.Add("Thread", threadInfoStr.ToString());
			}

			return dic;
		}

		protected string GetUserInfo(HttpContext context)
		{
			string result = null;
			if (context != null &&
					context.User != null &&
					context.User.Identity != null)
			{
				//user Info
				IPrincipal user = context.User;
				IIdentity identity = user.Identity;

				string roleInfo = String.Empty;
				try
				{
					string[] roleList = new string[] { };
					RolePrincipal rolePrincipal = user as RolePrincipal;
					if (rolePrincipal != null)
					{
						roleList = rolePrincipal.GetRoles();
					}

					if (roleList != null)
					{
						roleInfo = String.Join(", ", roleList);
					}
					else
					{
						roleInfo = "not specified";
					}
				}
				catch (Exception ex)
				{
					roleInfo = "Error {" + ex.Message + "}";
				}

				roleInfo = "{" + roleInfo + "}";
				result = String.Format("Name: {0}, AuthenticationType = {1}, IsAuthenticated = {2}; Roles = {3}",
				 identity.Name, identity.AuthenticationType, identity.IsAuthenticated.ToString(), roleInfo);
			}
			return result;
		}

		public override string ToString(bool includeAppInfo, bool includeCustomEventDetails)
		{
			return _message;
		}
	}
}
